/*
 * 
 * LegendShop 多用户商城系统
 * 
 *  版权所有,并保留所有权利。
 * 
 */
package com.legendshop.permission.dao.impl;

import com.legendshop.dao.impl.GenericDaoImpl;
import com.legendshop.dao.support.CriteriaQuery;
import com.legendshop.dao.support.PageSupport;
import com.legendshop.dao.support.QueryMap;
import com.legendshop.dao.support.SimpleSqlQuery;
import com.legendshop.framework.commond.JCFException;
import com.legendshop.oa.constants.ApplicationEnum;
import com.legendshop.oa.constants.SysParameterEnum;
import com.legendshop.oa.model.Function;
import com.legendshop.oa.model.Permission;
import com.legendshop.oa.model.PerssionId;
import com.legendshop.oa.model.UserDto;
import com.legendshop.oa.util.PropertiesUtil;
import com.legendshop.permission.dao.FunctionDao;
import com.legendshop.permission.dao.PermissionRowMapper;
import com.legendshop.util.AppUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * LegendShop 版权所有 2009-2011,并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示：在未取得LegendShop商业授权之前，您不能将本软件应用于商业用途，否则LegendShop将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站：http://www.legendesign.net
 * ----------------------------------------------------------------------------
 */
public class FunctionDaoImpl extends GenericDaoImpl<Function, Long> implements FunctionDao {

	/** The Constant logger. */
	private static final Log logger = LogFactory.getLog(FunctionDaoImpl.class);
	
	//后台权限 format url: list of function
	private Map<String,List<Function>> functionMap = null;

	/** The find function by role id. */
	private String findFunctionByRoleId;

	/** The find other function by role id. */
	private String findOtherFunctionByRoleId;

	/** The find other function by role id hql. */
	private String findOtherFunctionByRoleIdHQL;

	/** The find other function by role id hql count. */
	private String findOtherFunctionByRoleIdHQLCount;

	//find by functions
	private String loadUserByFunctionAllSQL = "SELECT count(*) FROM ls_usr_role ur ,ls_admin_user u " +
				"WHERE  ur.user_id=u.id   AND ur.role_id IN ( SELECT  p.role_id FROM ls_func f ,ls_perm  p  WHERE  f.id = p.function_id AND p.function_id =? ) ";
	
	private String loadUserByFunctionSQL = "SELECT u.real_name as realName, u.name, u.id, u.enabled,u.note FROM ls_usr_role ur ,ls_admin_user u " +
			"WHERE  ur.user_id=u.id  AND ur.role_id IN ( SELECT  p.role_id FROM ls_func f ,ls_perm  p  WHERE  f.id = p.function_id AND p.function_id =? ) ";
	
	//find by roles
	private String loadUserByRoleAllSQL = "SELECT COUNT(*) FROM ls_usr_role ur ,ls_admin_user u WHERE  ur.user_id=u.id  AND ur.role_id = ?";

	private String loadUserByRoleSQL = "SELECT u.real_name AS realName, u.name, u.id, u.enabled,u.note FROM ls_usr_role ur ,ls_admin_user u WHERE  ur.user_id=u.id  AND ur.role_id = ?";
	
	private String getFunctionByUserIdSQL = "select m.menu_id,m.name,f.protect_function,f.note,f.id,m.parent_id as parentName from ls_menu m,ls_func f where m.menu_id = f.menu_id and f.id in( select p.function_id from ls_perm p INNER JOIN ls_role r on p.role_id = r.id INNER JOIN ls_usr_role ur on ur.role_id = r.id where ur.user_id= ? ) order by m.parent_id ";

	private String getFunctionByUserIdAppNoSQL = "select m.menu_id,m.name,f.protect_function,f.note,f.id,m.parent_id as parentName from ls_menu m,ls_func f where m.menu_id = f.menu_id  and f.app_no = ? and f.id in( select p.function_id from ls_perm p INNER JOIN ls_role r on p.role_id = r.id INNER JOIN ls_usr_role ur on ur.role_id = r.id where ur.user_id= ? ) order by m.parent_id "; 
	
	private String  getSysFunctionByUserIdSQL = "select * from ls_func f where f.category=1 and f.id in ( select p.function_id from ls_perm p INNER JOIN ls_role r on p.role_id = r.id INNER JOIN ls_usr_role ur on ur.role_id = r.id where ur.user_id= ? ) ";
	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#setFindFunctionByRoleId(java.lang.String)
	 */
	
	public void init(){
		functionMap = new HashMap<String, List<Function>>();
		//查找后台权限
		List<Function> allFunc = query("select * from ls_func where url is not null AND app_no = ?", Function.class, ApplicationEnum.BACK_END.value());
		for (Function function : allFunc) {
			String funcUrl = function.getUrl();
			if(AppUtils.isNotBlank(funcUrl)){
				String[] urls = funcUrl.split(",");
				for (String url : urls) {
					String id = url.trim();
					if(AppUtils.isNotBlank(id)){
						List<Function> funcList = functionMap.get(id);
						if(AppUtils.isNotBlank(funcList)){
							funcList.add(function);
						}else{
							List<Function> list = new ArrayList<Function>();
							list.add(function);
							functionMap.put(id, list);
						}
						
					}

				}
			}
		}
		logger.info("function list init success");
	}
	
	/**
	 * 根据URL地质获取权限
	 * 
	 * @param url
	 * @return
	 */
	public List<Function> getFunctionsByUrl(String url) {
		List<Function> result = new ArrayList<Function>();
		PathMatcher matcher = new AntPathMatcher(); 
		for (String u : functionMap.keySet()) {
			if(matcher.match(u+"/**", url)){
			//if(url.startsWith(u)){
				result.addAll(functionMap.get(u));
			}
		}
		return result;
	}

	
	public void setFindFunctionByRoleId(String findFunctionByRoleId) {
		this.findFunctionByRoleId = findFunctionByRoleId;
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#setFindOtherFunctionByRoleId(java.lang.String)
	 */
	public void setFindOtherFunctionByRoleId(String findOtherFunctionByRoleId) {
		this.findOtherFunctionByRoleId = findOtherFunctionByRoleId;
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#setFindOtherFunctionByRoleIdHQL(java.lang.String)
	 */
	public void setFindOtherFunctionByRoleIdHQL(String findOtherFunctionByRoleIdHQL) {
		this.findOtherFunctionByRoleIdHQL = findOtherFunctionByRoleIdHQL;
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#FindFunctionByRoleId(java.lang.String)
	 */
	public List<Function> FindFunctionByRoleId(Long roleId) {
		return query(findFunctionByRoleId, Function.class, roleId);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#FindOtherFunctionByRoleId(java.lang.String)
	 */
	public List<Function> FindOtherFunctionByRoleId(Long roleId) {
		return query(findOtherFunctionByRoleId, Function.class, roleId);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#FindOtherFunctionByRoleId(com.legendshop.core.dao.support.HqlQuery, java.lang.String)
	 */
	public PageSupport FindOtherFunctionByRoleId(final SimpleSqlQuery query, Long roleId) throws JCFException {
		query.setQueryString(findOtherFunctionByRoleIdHQL);
		query.setAllCountString(findOtherFunctionByRoleIdHQLCount);
		query.setParam(new Object[] { roleId });
		return querySimplePage(query);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#savePermissions(java.util.List)
	 */
	public void savePermissions(final List<Permission> permissions) throws Exception {
		if(AppUtils.isBlank(permissions)){
			return;
		}
		List<Object[]> batchArgs = new ArrayList<Object[]>();
		for (Permission permission : permissions) {
			Object[] param = new Object[2];
			param[0] = permission.getId().getRoleId();
			param[1] = permission.getId().getFunctionId();
			batchArgs.add(param);
		}
		getJdbcTemplate().batchUpdate("insert into ls_perm (role_id,function_id) values (?,?)", batchArgs);
	}
	
	public PerssionId savePermission(Permission permission) {
		if(permission == null){
			return null;
		}
		 getJdbcTemplate().update("insert into ls_perm (role_id,function_id) values (?,?)", permission.getId().getRoleId(),permission.getId().getFunctionId());
		 return permission.getId();
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#DeletePermissionByFunctionId(java.util.List)
	 */
	public void DeletePermissionByFunctionId(List<Permission> permissions) {
		logger.info("DeletePermissionByFunctionId with size " + permissions.size());
		//deleteAll(permissions);
		if(AppUtils.isBlank(permissions)){
			return;
		}
		List<Object[]> batchArgs = new ArrayList<Object[]>();
		for (Permission permission : permissions) {
			Object[] param = new Object[2];
			param[0] = permission.getId().getRoleId();
			param[1] = permission.getId().getFunctionId();
			batchArgs.add(param);
		}
		getJdbcTemplate().batchUpdate("delete from ls_perm where role_id=? and function_id = ?", batchArgs);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#setFindOtherFunctionByRoleIdHQLCount(java.lang.String)
	 */
	public void setFindOtherFunctionByRoleIdHQLCount(String findOtherFunctionByRoleIdHQLCount) {
		this.findOtherFunctionByRoleIdHQLCount = findOtherFunctionByRoleIdHQLCount;
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#updateFunction(com.legendshop.model.entity.Function)
	 */
	public void updateFunction(Function function) {
		update(function);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#deleteFunction(com.legendshop.model.entity.Function)
	 */
	public void deleteFunction(Function function) {
		delete(function);
	}

	/* (non-Javadoc)
	 * @see com.legendshop.permission.dao.impl.FunctionDao#deleteFunction(java.lang.String)
	 */
	public boolean deleteFunction(Long functionId) {
		//删除角色和权限对应的关系
		update("delete from ls_perm where function_id = ?", functionId);
		return deleteById(functionId) > 0;
	}

	public Long saveFunction(Function function) {
		return save(function);
	}

	
	public PageSupport queryFunction(CriteriaQuery criteriaQuery) {
		return queryPage(criteriaQuery);
	}

	
	public List<Permission> queryPermission(Long functionId) {
		return query("select p.role_id, p.function_id from ls_perm p where p.function_id=?", new Object[]{functionId}, new PermissionRowMapper());
	}

	/**
	 * 获取权限ById
	 */
	public Function getFunctionById(Long id) {
		return getById(id);
	}


	/**
	 * 保存权限和菜单的关联关系
	 * 
	 * @param funcId
	 * @param menuId
	 * @return
	 */
	@Override
	public boolean saveFuncMenu(Long funcId, Long menuId) {
		int result = getJdbcTemplate().update("update ls_func set menu_id  = ? where id = ? ", menuId, funcId);
		return result > 0;
	}
	
	/**
	 * 获得所有权限
	 * 
	 * @return 权限列表
	 */
	@Override
	public List<Function> getAllFunction() {
		return query("select m.menu_id,m.name,f.protect_function,f.note,f.url,f.id,m.parent_id as parentName from ls_func f,ls_menu m where m.menu_id = f.menu_id order by m.parent_id ", Function.class);
	}
	
	@Override
	public List<Function> getAllFunction(String appNo) {
		return query(" SELECT m.menu_id,m.name,f.protect_function,f.note,f.id,f.url,m.parent_id AS parentName FROM ls_func f LEFT JOIN ls_menu m ON m.menu_id = f.menu_id  WHERE f.app_no = ? ORDER BY m.parent_id ", Function.class, appNo);
	}


	/**
	 * 根据菜单ID获取相关联的资源
	 * 
	 * @param menuId
	 * @return
	 */
	public List<Function> getFunctionsByMenuId(Long menuId) {
		return query(" select * from ls_func where menu_id = ? ",
				Function.class, menuId);
	}


	/**
	 * 根据用户ID查询用户拥有的操作权限信息
	 * @param userId
	 * @return
	 */
	public List<Function> getFunctionByUserId(Long userId) {
		return query(getFunctionByUserIdSQL,Function.class, userId);
	}
	
	@Override
	public List<Function> getFunctionByUserId(Long userId, String appNo) {
		return query(getFunctionByUserIdAppNoSQL, Function.class, appNo, userId);
	}

	
	/**
	 * 根据用户ID查询用户拥有的系统权限信息
	 * @param userId
	 * @return
	 */
	public List<Function> getSysFunctionByUserId(Long userId) {
		return query(getSysFunctionByUserIdSQL, Function.class, userId);
	}
	
	/**
	 * 根据权限ID获取菜单ID列表
	 */
	@Override
	public List<Long> getMenuIdSByFuncId(Long funcId) {
		return query(" select menu_id from ls_func where id  = ?", Long.class, funcId);
	}

	/**
	 * 根据权限查找用户列表
	 */
	@Override
	public PageSupport loadUserByFunction(String curPageNO, String userName, Long funcId) {
   		SimpleSqlQuery query = new SimpleSqlQuery(UserDto.class,PropertiesUtil.getObject(SysParameterEnum.PAGE_SIZE, Integer.class), curPageNO);
   		
   		String queryAllSQL = loadUserByFunctionAllSQL;
   		String querySQL = loadUserByFunctionSQL;
   		
   		QueryMap map = new QueryMap();
   		map.put("funcId",funcId);
   		if(AppUtils.isNotBlank(userName)){
   			map.like("userName", userName);
   			queryAllSQL = queryAllSQL + " AND u.real_name LIKE  ?";
   			querySQL = querySQL + " AND u.real_name LIKE  ?";
   		}
   		 query.setAllCountString(queryAllSQL);
   		 query.setQueryString(querySQL);
   		 query.setParam(map.toArray());
		return querySimplePage(query);
	}
	
	@Override
	public PageSupport loadUserByRole(String curPageNO, String userName, Long roleId) {
   		SimpleSqlQuery query = new SimpleSqlQuery(UserDto.class,PropertiesUtil.getObject(SysParameterEnum.PAGE_SIZE, Integer.class), curPageNO);
   		
   		String queryAllSQL = loadUserByRoleAllSQL;
   		String querySQL = loadUserByRoleSQL;
   		
   		QueryMap map = new QueryMap();
   		map.put("roleId",roleId);
   		if(AppUtils.isNotBlank(userName)){
   			map.like("userName", userName);
   			queryAllSQL = queryAllSQL + " AND u.real_name LIKE  ?";
   			querySQL = querySQL + " AND u.real_name LIKE  ?";
   		}
   		 query.setAllCountString(queryAllSQL);
   		 query.setQueryString(querySQL);
   		 query.setParam(map.toArray());
		return querySimplePage(query);
	}

	@Override
	public List<Permission> getPermissionByRoleId(final Long roleId) {
		return query("SELECT * FROM ls_perm WHERE role_id = ?", new Object[]{ roleId }, new RowMapper<Permission>() {
			@Override
			public Permission mapRow(ResultSet rs, int rowNum) throws SQLException {
				Permission p = new Permission();
				PerssionId id = new PerssionId();
				id.setFunctionId(rs.getLong("function_id"));
				id.setRoleId(roleId);
				p.setId(id);
				return p;
			}
		});
	}

	@Override
	public List<Function> getSysFunctionByUserId(Long userId, String appNo) {
		return query(
				"SELECT * FROM ls_func f WHERE f.category=1  AND f.app_no =? AND f.id IN( SELECT p.function_id FROM ls_perm p INNER JOIN ls_role r ON p.role_id = r.id INNER JOIN ls_usr_role ur ON ur.role_id = r.id WHERE r.app_no =  ? AND ur.user_id= ? )",
				Function.class, appNo, appNo, userId);
	}

	@Override
	public List<Function> getSysFunctionByAppNo(String appNo) {
		return query("SELECT * FROM ls_func f WHERE f.category=1  AND f.app_no =?",Function.class, appNo);
	}

	@Override
	public PageSupport<Function> queryFunction(String curPageNO, Function function) {
		// Qbc查找方式
		CriteriaQuery cq = new CriteriaQuery(Function.class, curPageNO);
		cq.setPageSize(PropertiesUtil.getObject(SysParameterEnum.PAGE_SIZE, Integer.class));
		String name = function.getName();
		if (!AppUtils.isBlank(name)) {
			cq.like("name", "%" + name.trim() + "%");// 1
		}
		cq.eq("category", function.getCategory());
		cq.eq("appNo", function.getAppNo());
		cq.eq("menuId", function.getMenuId());
		cq.addOrder("desc", "name");
		return queryPage(cq);
	}



}